﻿using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace CountTools
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class CodeName : IExternalCommand
    {
        private string path;

        public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elements)
        {
            UIDocument uidoc = cmdData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            List<string> elementTypes = new List<string>();

            FilteredElementCollector collectorColumn = new FilteredElementCollector(doc);
            collectorColumn.OfCategory(BuiltInCategory.OST_StructuralColumns).OfClass(typeof(FamilyInstance));
            if (collectorColumn.Count() > 0)
            {
                elementTypes.Add("柱");
            }

            FilteredElementCollector collectorBeam = new FilteredElementCollector(doc);
            collectorBeam.OfCategory(BuiltInCategory.OST_StructuralFraming).OfClass(typeof(FamilyInstance));
            if (collectorBeam.Count() > 0)
            {
                elementTypes.Add("梁");
            }

            FilteredElementCollector collectorWall = new FilteredElementCollector(doc);
            collectorWall.OfCategory(BuiltInCategory.OST_Walls).OfClass(typeof(Wall));
            if (collectorWall.Count() > 0)
            {
                elementTypes.Add("墙");
            }

            FilteredElementCollector collectorFloor = new FilteredElementCollector(doc);
            collectorFloor.OfCategory(BuiltInCategory.OST_Floors).OfClass(typeof(Floor));
            if (collectorFloor.Count() > 0)
            {
                elementTypes.Add("板");
            }

            //elementTypes.Add("钢筋");

            Dictionary<string, List<ElementId>> elementsList = new Dictionary<string, List<ElementId>>();

            this.path = doc.PathName;
            int lastChar = path.LastIndexOf(@"\");
            path = path.Remove(lastChar + 1);
            path += doc.Title.Substring(0, doc.Title.Length - 4) + "清单规则.xml";
            CodeNameRuleForm codeNameRuleForm = new CodeNameRuleForm(elementTypes, path);
            codeNameRuleForm.ShowDialog();

            if (codeNameRuleForm.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                List<string> list = codeNameRuleForm.CodeList;
                XmlDocument xml = new XmlDocument();
                string newPath = path.Replace("清单规则", "算量信息");
                if (File.Exists(newPath))
                {
                    xml.Load(newPath);
                }
                else
                {
                    XmlNode title = xml.CreateElement("算量信息");
                    xml.AppendChild(title);
                    xml.Save(newPath);
                }

                Transaction trans = new Transaction(doc, "CodeName");
                trans.Start();
                ElementClassFilter familyClassFilter = new ElementClassFilter(typeof(FamilyInstance));//类型
                ElementClassFilter hostClassFilter = new ElementClassFilter(typeof(HostObject));//宿主类型
                LogicalOrFilter elementLogicalFilter = new LogicalOrFilter(familyClassFilter, hostClassFilter);
                FilteredElementCollector collector = new FilteredElementCollector(doc);
                collector.WherePasses(elementLogicalFilter);
                IList<Element> columnsList = collector.ToElements();
                int count = 0;
                ProgressBarExport progressBar = new ProgressBarExport();
                progressBar.Text = "匹配项目名称";
                progressBar.progressBarEx.Minimum = 0;
                progressBar.SetTextInfo("生成构件编码(" + count.ToString() + "/" + columnsList.Count.ToString() + ")", 0L);
                progressBar.Show();
                progressBar.progressBarEx.Maximum = columnsList.Count;

                foreach (Element element in columnsList)
                {
                    //if (xml.ChildNodes.Count > 0)
                    //{
                    //    XmlNode node = xml.SelectSingleNode("算量信息").SelectSingleNode("ID" + element.Id.ToString());
                    //    if (node != null)
                    //    {
                    //        XmlNode barsnode = node.SelectSingleNode("钢筋集");
                    //        foreach (XmlNode xn1 in barsnode.ChildNodes)
                    //        {
                    //            XmlElement dataName = xml.CreateElement("项目名称");
                    //            dataName.InnerText = "010515001 现浇钢筋";
                    //            xn1.AppendChild(dataName);
                    //        }
                    //    }
                    //}

                    string key = element.Category.Name + "$";
                    string familyTypeName = element.get_Parameter(BuiltInParameter.ELEM_FAMILY_AND_TYPE_PARAM).AsValueString();
                    key += familyTypeName.Split(':')[0] + "$";
                    familyTypeName = familyTypeName.Split(':')[1].Remove(0, 1);
                    key += familyTypeName + "$";
                    familyTypeName = familyTypeName.Split('_')[0];
                    string code = GetCodeName(list, familyTypeName);
                    if (!string.IsNullOrEmpty(code))
                    {
                        key += code;
                    }
                    else
                    {
                        key += "未知";
                    }

                    if (elementsList.ContainsKey(key))
                    {
                        elementsList[key].Add(element.Id);
                    }
                    else
                    {
                        elementsList.Add(key, new List<ElementId>());
                        elementsList[key].Add(element.Id);
                    }
                    count++;
                    progressBar.PerformStep();
                    progressBar.SetTextInfo("生成构件编码(" + count.ToString() + "/" + columnsList.Count.ToString() + ")", 0L);
                    if (progressBar.progressBarEx.Value == columnsList.Count)
                    {
                        progressBar.Dispose();
                    }
                    if (progressBar.bAbort)
                    {
                        trans.RollBack();
                        progressBar.Dispose();
                        progressBar.Close();
                        return Result.Cancelled;
                    }

                }
                xml.Save(newPath);
                trans.Commit();
                progressBar.Dispose();
            }

            else
            {
                return Result.Cancelled;
            }

            CodeNameResultForm resultForm = new CodeNameResultForm(elementsList, path);
            resultForm.ShowDialog();

            if (resultForm.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                path = path.Replace("清单规则", "算量信息");
                XmlDocument xml = new XmlDocument();

                XmlNode title = null;
                if (File.Exists(path))
                {
                    xml.Load(path);
                    title = xml.SelectSingleNode("算量信息");
                }
                else
                {
                    title = xml.CreateElement("算量信息");
                    xml.AppendChild(title);
                    xml.Save(path);
                }


                for (int i = 0; i < resultForm.ResultList.Count; i++)
                {
                    foreach (string key in elementsList.Keys)
                    {
                        if (key.Contains(resultForm.ResultList[i].Split('$')[0]))
                        {
                            for (int j = 0; j < elementsList[key].Count; j++)
                            {
                                XmlNode elementId = null;
                                XmlNode name = null;
                                try
                                {
                                    elementId = title.SelectSingleNode("ID" + elementsList[key][j].ToString());
                                    name = elementId.SelectSingleNode("项目名称");
                                }

                                catch
                                {
                                    elementId = xml.CreateElement("ID" + elementsList[key][j].ToString());
                                    title.AppendChild(elementId);
                                    name = xml.CreateElement("项目名称");
                                    XmlNode code = xml.CreateElement("项目编码");
                                    XmlNode text = xml.CreateElement("项目特征");
                                    XmlNode count = xml.CreateElement("工程量");
                                    XmlNode unit = xml.CreateElement("单位");
                                    elementId.AppendChild(name);
                                    elementId.AppendChild(code);
                                    elementId.AppendChild(text);
                                    elementId.AppendChild(count);
                                    elementId.AppendChild(unit);
                                }

                                name.InnerText = resultForm.ResultList[i].Split('$')[1].Split(' ')[0] + " " + resultForm.ResultList[i].Split('$')[1].Split(' ')[1];

                            }
                            break;
                        }
                    }
                }

                xml.Save(path);
                TaskDialog.Show("Revit", "项目名称匹配成功！！");
            }



            return Result.Succeeded;
        }



        private string GetCodeName(List<string> list, string familyTypeName)
        {
            string codeName = "";
            foreach (string str in list)
            {
                string keyString = str.Split('-')[2];
                string code = str.Split('-')[0] + " " + str.Split('-')[1];
                var keys = keyString.Split(',');
                foreach (string key in keys)
                {
                    if (familyTypeName == key)
                    {
                        return code;
                    }
                }
            }
            return codeName;
        }






    }
}
